#include <stdio.h>
#include <stdlib.h>
#include "algorithm.h"

/**
 * @brief  算法接口
 * @param  input            输入参数
 * @param  output           输出参数
 * @return int32_t          返回成功或者失败，RETURN_OK 或 RETURN_ERROR
 */
 static int mintime=0x7fffffff;
int32_t dfs(int32_t vis[],int32_t q[],const InputParam *input, OutputParam *output,int32_t time){
    if (time>mintime){
        return mintime;
    }
    if (q[0]==input->ioVec.len){
        if (time<mintime){
            mintime=time;
            for(int i=0;i<input->ioVec.len;i++){
                output->sequence[i]=input->ioVec.ioArray[q[i+1]].id;
            }
            output->len=q[0];
        }
        return mintime;
    }
    for(int i=0;i<input->ioVec.len;i++){
        if (!vis[i]){
            HeadInfo start;
            if  (q[0]==0) start=input->headInfo;
            else {
                start.wrap=input->ioVec.ioArray[q[q[0]-1]].wrap;
                start.lpos= input->ioVec.ioArray[q[q[0]-1]].endLpos;
                start.status= HEAD_RW;
            }
            HeadInfo end = {input->ioVec.ioArray[i].wrap, input->ioVec.ioArray[i].startLpos, HEAD_RW};
            q[++q[0]]=i; 
            vis[i]=1;
            dfs(vis,q,input,output,time+SeekTimeCalculate(&start, &end));
            vis[i]=0;
            q[0]--;
        }
    }
    return mintime;
}
int32_t IOScheduleAlgorithm(const InputParam *input, OutputParam *output)
{
    int32_t ret;

    /* 算法示例：先入先出算法 */
    int32_t* vis=(int32_t *)malloc(input->ioVec.len*sizeof(int32_t));
    for(int i=0;i<input->ioVec.len;i++) vis[i]=0;
    int32_t* q=(int32_t *)malloc((input->ioVec.len+1)*sizeof(int32_t));
    q[0]=0;
    int32_t mintime=dfs(vis,q,input,output,0);
    printf("\t%d ms\n",mintime);
    /*HeadInfo end = {input->ioVec.ioArray[0].wrap, input->ioVec.ioArray[0].startLpos, HEAD_RW};
    printf("\t%d ms\n",SeekTimeCalculate(&(input->headInfo),&end));
    */
    int32_t seekT = 0;
    for(int i=0;i<output->len;i++){
        HeadInfo start;
        
            if  (i==0) start=input->headInfo;
            else {
                start.wrap=input->ioVec.ioArray[output->sequence[i-1]].wrap;
                start.lpos= input->ioVec.ioArray[output->sequence[i-1]].endLpos;
                start.status= HEAD_RW;
            }   
        HeadInfo end = {input->ioVec.ioArray[output->sequence[i]].wrap, input->ioVec.ioArray[output->sequence[i]].startLpos, HEAD_RW};
        AccessTime accessTime = {0};
        OutputParam *o1 = (OutputParam *)malloc(sizeof(OutputParam));
        o1->len =1;
        o1->sequence = (uint32_t *)malloc(output->len * sizeof(uint32_t));
        o1->sequence[0]=1;
        InputParam *in1=(InputParam *)malloc(sizeof(InputParam));
        in1->headInfo=start;
        in1->ioVec.len=1;
        in1->ioVec.ioArray=(IOUint *)malloc(in1->ioVec.len*sizeof(IOUint));
        in1->ioVec.ioArray[0]=input->ioVec.ioArray[output->sequence[i]];
        in1->ioVec.ioArray[0].id=1;
        TotalAccessTime(in1, o1, &accessTime);
        printf("\t%d:%d ms\n",output->sequence[i],accessTime.addressDuration);
        seekT+=accessTime.addressDuration;
        free(o1->sequence);
        free(o1);
        free(in1->ioVec.ioArray);
        free(in1);
    }
    printf("\ttotal:%d ms\n",seekT);
    /* 调用公共函数示例：调用电机寻址、带体磨损、电机磨损函数 
    HeadInfo start = {input->ioVec.ioArray[0].wrap, input->ioVec.ioArray[0].endLpos, HEAD_RW};
    HeadInfo end = {input->ioVec.ioArray[1].wrap, input->ioVec.ioArray[1].endLpos, HEAD_RW};
    int32_t seekT = 0;
    int32_t beltW = 0;
    int32_t motorW = 0;
       for (uint32_t i = 0; i < 10000; i++) {
           seekT = SeekTimeCalculate(&start, &end);
           beltW = BeltWearTimes(&start, &end, NULL);
           motorW = MotorWearTimes(&start, &end);
       }
*/
    /* 调用公共函数示例：调用IO读写时间函数 
    uint32_t rwT = ReadTimeCalculate(abs(input->ioVec.ioArray[0].endLpos - input->ioVec.ioArray[0].startLpos));
*/
    free(vis);
    free(q);
    return RETURN_OK;
}

/**
 * @brief  算法运行的主入口
 * @param  input            输入参数
 * @param  output           输出参数
 * @return uint32_t          返回成功或者失败，RETURN_OK 或 RETURN_ERROR
 */
int32_t AlgorithmRun(const InputParam *input, OutputParam *output)
{
    int32_t ret;

    ret = IOScheduleAlgorithm(input, output);
    return RETURN_OK;
}
